import {
  AppContext,
  Component,
  ComponentInternalInstance,
  ComponentPublicInstance,
  h,
  render,
  VNode,
} from 'vue';
import type { ModalProps, ModalFuncProps } from 'ant-design-vue';
import { cp } from './custom-dialog';

let vms = {} as ComponentPublicInstance<customProps>;
type customProps = ModalProps | ModalFuncProps;
export interface CommandComponent {
  (options: customProps): VNode;
  close?: () => void;
}
const getAppendToElement = (props: customProps): HTMLElement => {
  let getContainer: HTMLElement | null = document.body;
  if (props.getContainer) {
    if (typeof props.getContainer === 'string') {
      getContainer = document.querySelector<HTMLElement>(props.getContainer);
    }
    if (props.getContainer instanceof HTMLElement) {
      getContainer = props.getContainer;
    }
    if (!(getContainer instanceof HTMLElement)) {
      getContainer = document.body;
    }
  }
  return getContainer;
};

const initInstance = <T extends Component>(
  com: T,
  props: customProps,
  container: HTMLElement,
  appContext: AppContext | null = null,
) => {
  const customComponent = cp(com, props);
  const vNode = h(customComponent);
  vNode.appContext = appContext;
  render(vNode, container);

  getAppendToElement(props).appendChild(container);
  return vNode;
};
export const useCustomDialog = <T extends Component>(
  com: T,
  currentInstance: ComponentInternalInstance | null,
  props: customProps,
): any => {
  const appContext = currentInstance?.appContext;
  // 补丁：Component中获取当前组件树的provides
  if (appContext) {
    const currentProvides = (currentInstance as any)?.provides;
    Reflect.set(appContext, 'provides', {
      ...appContext.provides,
      ...currentProvides,
    });
  }

  const container = document.createElement('div');

  const closeDialog = () => {
    vms.visible = false;
    setTimeout(() => {
      render(null, container);
      container.parentNode?.removeChild(container);
    }, 500);
  };
  if (typeof props.onCancel !== 'function') {
    props.onCancel = closeDialog;
  } else {
    const originOnClose = props.onCancel;
    props.onCancel = (e: MouseEvent) => {
      originOnClose?.(e);
      closeDialog();
    };
  }
  const vNode = initInstance<T>(com, props, container, appContext);
  vms = vNode.component?.proxy as ComponentPublicInstance<customProps>;
  return [closeDialog];
};
